﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EPiServer.Web.Hosting;
using System.Web;
using System.IO;
using EPiServer;
using System.Web.Hosting;
using Microsoft.WindowsAzure.StorageClient;
using EPiServer.Security;

namespace DBLOG.Azure.VirtualPathProvider.Entities
{
    public class CloudFile : UnifiedFile
    {
        #region Public properties

        /// <summary>
        /// Gets or sets the Windows Azure container name for the file
        /// </summary>
        public string ContainerName { get; set; }

        /// <summary>
        /// Gets or sets the file GUID
        /// </summary>
        public Guid FileGuid { get; set; }

        public override string PermanentLinkVirtualPath
        {
            // TODO: Azure support?
            get { return String.Empty; }
        }

        #endregion

        #region Private properties

        private CloudBlob _Blob { get; set; }
        private long _Length { get; set; }
        private DateTime _Changed { get; set; }
        private DateTime _Created { get; set; }

        #endregion

        private string _CacheKey { get { return this.FileGuid.ToString(); } }

        public CloudFile(UnifiedDirectory directory, VirtualPathUnifiedProvider provider, string virtualPath, bool byPassAccessCheck, string containerName)
            : base(directory, provider, HttpUtility.UrlDecode(virtualPath), byPassAccessCheck)
        {
            this.ContainerName = containerName;

            virtualPath = HttpUtility.UrlDecode(virtualPath);

            CloudBlob blob = BlobStorageDataFactory.Instance.GetFile(virtualPath, containerName);

            if (blob.Exists())
            {
                this._Blob = blob;

                this._Blob.FetchAttributes();
                this._Length = this._Blob.Properties.Length;
                this._Created = this._Blob.Properties.LastModifiedUtc;
                this._Changed = this._Blob.Properties.LastModifiedUtc;
            }
            else
            {
                this._Length = 0;
                this._Created = DateTime.Now;
                this._Created = DateTime.Now;
            }
        }

        public override Stream Open()
        {
            return this.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
        }

        public override Stream Open(FileMode mode)
        {
            return this.Open(mode, FileAccess.Read, FileShare.Read);
        }

        public override Stream Open(FileMode mode, FileAccess access)
        {
            return this.Open(mode, access, FileShare.ReadWrite);
        }

        public override Stream Open(FileMode mode, FileAccess access, FileShare share)
        {
            if (mode == FileMode.CreateNew || mode == FileMode.OpenOrCreate || mode == FileMode.Create)
            {
                CloudStream stream = new CloudStream(this);

                return stream;
            }
            else
            {
                CloudBlob blob = BlobStorageDataFactory.Instance.GetFile(this.VirtualPath, this.ContainerName);

                MemoryStream stream = new MemoryStream();

                blob.DownloadToStream(stream);

                stream.Seek(0, SeekOrigin.Begin);

                return stream;
            }
        }

        public override void Delete()
        {
            BlobStorageDataFactory.Instance.DeleteFile(this.VirtualPath, this.ContainerName);
        }

        public override long Length
        {
            get
            {
                return this._Length;
            }
        }

        public override DateTime Changed
        {
            get
            {
                return this._Changed;
            }
        }

        public override DateTime Created
        {
            get
            {
                return this._Created;
            }
        }

        public override IUnifiedSummary Summary
        {
            get
            {
                return new CloudSummary(this._Blob);
            }
        }

        public override UnifiedDirectory Parent
        {
            get
            {
                return (HostingEnvironment.VirtualPathProvider.GetDirectory(VirtualPathUtility.GetDirectory(VirtualPath)) as CloudDirectory);
            }
        }

        public override AccessLevel QueryAccess()
        {
            // HACK: Bypass access
            return AccessLevel.Administer;
        }

        public override bool QueryDistinctAccess(AccessLevel access)
        {
            return true;
        }

        public override string Name
        {
            get
            {
                return HttpUtility.UrlDecode(base.Name);
            }
        }

        public override void MoveTo(string newVirtualPath)
        {
            UnifiedVirtualPathEventArgs unifiedVirtualPathEventArgs = new UnifiedVirtualPathEventArgs(newVirtualPath, base.VirtualPath);

            this.OnMoving(unifiedVirtualPathEventArgs);

            if (unifiedVirtualPathEventArgs.Cancel)
            {
                throw new InvalidOperationException("The operation have been cancelled because: " + unifiedVirtualPathEventArgs.Reason);
            }

            CloudDirectory directory = VirtualPathHandler.Instance.GetDirectory(VirtualPathUtility.GetDirectory(newVirtualPath), this.BypassAccessCheck) as CloudDirectory;

            BlobStorageDataFactory.Instance.MoveFile(directory, this._Blob, newVirtualPath, this.ContainerName);

            this.OnMoved(unifiedVirtualPathEventArgs);
        }

        public override void CopyTo(string newVirtualPath)
        {
            UnifiedVirtualPathEventArgs unifiedVirtualPathEventArgs = new UnifiedVirtualPathEventArgs(newVirtualPath, base.VirtualPath);

            this.OnCopying(unifiedVirtualPathEventArgs);

            if (unifiedVirtualPathEventArgs.Cancel)
            {
                throw new InvalidOperationException("The operation have been cancelled because: " + unifiedVirtualPathEventArgs.Reason);
            }

            CloudDirectory directory = VirtualPathHandler.Instance.GetDirectory(VirtualPathUtility.GetDirectory(newVirtualPath), this.BypassAccessCheck) as CloudDirectory;

            BlobStorageDataFactory.Instance.CopyFile(directory, this._Blob, newVirtualPath, this.ContainerName);

            this.OnCopied(unifiedVirtualPathEventArgs);
        }
    }
}
